<?php

class Dao_AbstractDAO {
	protected $db;
	protected $tableName;
	protected $key;
	protected $classModel;
	protected $idUser;

	protected function __construct($db = null) {
		if (! isset($db) || $db === null) {
			$db = new mysqli(DB_HOST, DB_USERNAME, DB_PASS, DB_DATABASE_NAME);
			$this->db = $db;
			$db->query('set names "utf8"');
		} else {
			$this->db = $db;
		}

		$this->idUser = null;
	}

	public function setIdUser($idUser) {
		$this->idUser = $idUser;
	}

	public function getAll() {
		$query = "select * from " . $this->tableName;
		return $this->getObjects($query);
	}

	protected function getObjects($res) {
		$db = $this->db;

		$value = array();

		if ($res) {
			while ( $row = $res->fetch_assoc() ) {
				$value[] = new $this->classModel($row);
			}
		}

		return $value;
	}

	public function startTransaction() {
		$db = $this->db;
		$db->autocommit(FALSE);
	}

	public function commitTransaction() {
		$db = $this->db;
		$db->commit();
		$db->autocommit(TRUE);
	}

	public function rollBackTransaction() {
		$db = $this->db;
		$db->rollback();
		$db->autocommit(TRUE);
	}

	protected function query($query) {
		$db = $this->db;
		$res = $db->query($query);
		if ($res === false) {
			throw new Exception(mysqli_error($this->db));
		}

		$value = array();

		if ($res) {
			while ( $row = $res->fetch_assoc() ) {
				$value[] = $row;
			}
		}

		return $value;
	}

	protected function getList($query) {
		$db = $this->db;
		$res = $db->query($query);
		if ($res === false) {
			throw  new Exception(mysqli_error($db));
		}
		return $this->getObjects($res);
	}

	protected function getOneObject($query) {
		$list = $this->getList($query);
		if(count($list) > 0) {
			return $list[0];
		} else {
			return null;
		}
	}

	protected function getCount($query) {
		$db = $this->db;
		$res = $db->query($query);
		//return $res[0]['cnt'];
		return $res->num_rows;
	}

	public function insertModel(Model_AbstractModel $model) {
		$arr = $model->toArray();
		$sql = $this->createSQLInsert($arr);
		$res = $this->db->query($sql);
		if ($res === false) {
			throw new Exception(mysqli_error($this->db));
		}

		return $res;
	}

	public function getInsertedId() {
		return $this->db->insert_id;
	}

	public function getMaxId() {
		$query = " select max(id) as mx from $this->tableName ";
		$res = $this->query($query);
		if (count($res) > 0) {
			return $res[0]['mx'];
		} else {
			return 0;
		}
	}

	private function createSQLInsert($arr) {
		$str = '';
		$str .= " INSERT INTO $this->tableName (";
		$index = 0;
		foreach ($arr as $key => $value) {
			if ($index != 0) {
				$str .= " , ";
			}

			$index++;
			$str .= $key ;
		}

		$str .= " , insert_time , ";
		$str .= " id_user ";
		$str .= " )";

		$str .= " VALUES (";

		$index = 0;

		foreach ($arr as $key => $value) {
			//$value = $this->removeEscape($value);
			if ($index != 0) {
				$str .= " , ";
			}
				$index++;

			if ($value === null || trim($value) === '') {
				$str .= " null " ;
			} else {
				$str .= " '" . $value . "' " ;
			}

		}

		$str .= " , now() , ";
		$str .= " '$this->idUser' ";

		$str .= " )";

		return $str;
	}

	public function updateModelById(Model_AbstractModel $model) {
		$arr = $model->toArray();
		$sql = $this->createSQLUpdate($arr);
		$res = $this->db->query($sql);
		if ($res === false) {
			throw new Exception(mysqli_error($this->db));
		}

		return $res;
	}

	private function createSQLUpdate($arr) {
		$str = '';
		$str .= " UPDATE  `$this->tableName` SET ";
		$index = 0;

		foreach ($arr as $key => $value) {
			//$value = $this->removeEscape($value);
			if ($index != 0) {
				$str .= " , ";
			}

			$index++;
			$str .= $key . " = '" .$value . "' " ;
		}

		$str .= " , update_time = NOW() , ";
		$str .= " id_user = '$this->idUser' ";

		$str .= " WHERE ";

		$str .= " $this->key =  '" . $arr[$this->key] . "'" ;

		return $str;
	}

	/**
	 * append Limit to SQL
	 * @param string $query
	 * @param int $number
	 * @return string
	 */
	protected function appendLimit($query, $start, $number) {

		if ($start !== null && $number !== null) {
			$query .= " limit $start, $number ";
		}

		return $query;
	}

	public function removeEscape($str) {
		$str = $this->db->real_escape_string($str);
		return $str;
	}

	public function getModelById($id) {
		$sql = $this->createSQLGetById($id);
		$model = $this->getOneObject($sql);
		return $model;
	}

	public function createSQLGetById($id) {
		$query = " SELECT * FROM $this->tableName ";
		$query .= " WHERE $this->key = '$id'";
		return $query;
	}

}